package ysq.xyg.base.aspect;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import ysq.xyg.base.util.BaseConstant;
import ysq.xyg.base.util.BaseUtil;
import ysq.xyg.sys.model.po.SysLogUse;
import ysq.xyg.sys.service.SysLogUseService;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

/**
 *@Author: YuShengQiang
 *@Date: 2018-11-28 15:54
 *@Description: 操作日志记录处理
 */
@Aspect
@Component
public class LogUseAspect {
    @Resource
    private SysLogUseService sysLogUseService;


    // 配置织入点
    @Pointcut("@annotation(ysq.xyg.base.aspect.BaseLog)")
    public void logPointCut()
    {
    }

    /**
     * 前置通知 用于拦截操作
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        handleLog(joinPoint, null);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfter(JoinPoint joinPoint, Exception e) {
        handleLog(joinPoint, e);
    }

    protected void handleLog(final JoinPoint joinPoint, final Exception e){
        try{
            // 获得注解
            BaseLog controllerLog = getAnnotationLog(joinPoint);
            if (controllerLog == null){
                return;
            }
            //常见日志实体对象
            SysLogUse operLog = new SysLogUse();
            operLog.setId(RandomUtil.randomNumbers(32));
            operLog.setCreateTime(new Date());
            //获取登录用户账户
            /*Object principal = SecurityUtils.getSubject().getPrincipal();
            if (principal != null) {
                String userId = ((BaseUser) principal).getId();
                operLog.setOperatorId(userId);
            }*/
            operLog.setOperStatus(BaseConstant.SYS_OPERATOR_STATUS_SUCCESS);
            // 获取request
            HttpServletRequest request =BaseUtil.getRequest();
            // 设置IP地址
            operLog.setOperIp(ServletUtil.getClientIP(request));
            operLog.setOperUrl(request.getRequestURI());

            if (e != null){
                operLog.setOperStatus(BaseConstant.SYS_OPERATOR_STATUS_FAIL);
                operLog.setErrorMsg(StrUtil.subWithLength(e.getMessage(), 0, 2000));
            }
            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setMethod(className + "." + methodName + "()");
            // 处理设置注解上的参数
            getControllerMethodDescription(controllerLog, operLog);
            // 保存数据库
            sysLogUseService.insert(operLog);
            //AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
        }catch (Exception exp){
            // 记录本地异常日志
            /*log.error("==前置通知异常==");
            log.error("异常信息:{}", exp.getMessage());*/
            exp.printStackTrace();
        }
    }
    /**
     * 是否存在注解，如果存在就获取
     */
    private BaseLog getAnnotationLog(JoinPoint joinPoint) throws Exception
    {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null)
        {
            return method.getAnnotation(BaseLog.class);
        }
        return null;
    }
    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @return 方法描述
     * @throws Exception
     */
    public void getControllerMethodDescription(BaseLog log, SysLogUse operLog) throws Exception
    {
        // 设置action动作
        operLog.setBusinessType(log.businessType());
        //模块
        operLog.setModuleName(log.module());
        //类
        operLog.setClassName(log.className());
        //方法
        operLog.setMethodName(log.methods());
        // 设置操作人类别
        operLog.setOperatorType(log.operatorType());
        // 是否需要保存request，参数和值
        if (log.isSaveRequestData()){
            // 获取参数的信息，传入到数据库中。
            setRequestValue(operLog);
        }
    }
    /**
     * 获取请求的参数，放到log中
     *
     * @param operLog 操作日志
     * @throws Exception 异常
     */
    private void setRequestValue(SysLogUse operLog) throws Exception
    {
        Map<String, String> map=ServletUtil.getParamMap(BaseUtil.getRequest());
        String s="";
        if(map!=null&&map.size()>0){
            s=JSON.toJSONString(map);
        }
        operLog.setOperParam(s);
    }
}
